<!DOCTYPE html>
<html lang="zh-CN">


<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/alwaysblog/favicon_1.ico">
  <link rel="icon" type="image/png" href="/alwaysblog/favicon_1.ico">
  <meta name="viewport"
        content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="author" content="张小剩">
  
    <meta name="description" content="折腾是一种乐趣，求知是一种追求！">
  
  
    <meta name="keywords" content="软件测试,性能测试," />
  
  <meta http-equiv="Cache-Control" content="no-transform" />
  <meta http-equiv="Cache-Control" content="no-siteapp" />
  <title>性能测试基础 - 张小剩的博客</title>
  <link rel="stylesheet" href="https://cdn.staticfile.org/font-awesome/5.10.0/css/all.min.css"  >
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/css/bootstrap.min.css"  >
<link rel="stylesheet" href="https://cdn.staticfile.org/mdbootstrap/4.8.7/css/mdb.min.css"  >
<link rel="stylesheet" href="https://cdn.staticfile.org/github-markdown-css/3.0.1/github-markdown.min.css"  >

<link rel="stylesheet" href="//at.alicdn.com/t/font_1067060_qzomjdt8bmp.css">


  <link rel="stylesheet" href="/alwaysblog/lib/prettify/tranquil-heart.min.css"  >


  <link rel="stylesheet" href="https://cdn.staticfile.org/fancybox/3.5.7/jquery.fancybox.min.css"  >

<link rel="stylesheet" href="/alwaysblog/css/main.css"  >
<script src="https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js" ></script>
  <style type="text/css">
    .banner-bg {
      
        background-image: url('/alwaysblog/static/images/wallhaven-8opx8k.jpg');
      
      background-position: center;
      background-repeat: repeat-y;
      background-size: cover;
      background-attachment: fixed;
    }
  </style>
<meta name="generator" content="Hexo 5.4.1"><link rel="alternate" href="/alwaysblog/atom.xml" title="张小剩的博客" type="application/atom+xml">
</head>

<body class="banner-bg">
  <header style="height: 70vh;">
    <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand"
       href="/alwaysblog/">&nbsp;<strong>张小剩的博客</strong>&nbsp;</a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
          <li class="nav-item">
            <a class="nav-link" href="/alwaysblog/">主页</a>
          </li>
        
          
          
          
          
          <li class="nav-item">
            <a class="nav-link" href="/alwaysblog/archives/">归档</a>
          </li>
        
          
          
          
          
          <li class="nav-item">
            <a class="nav-link" href="/alwaysblog/categories/">分类</a>
          </li>
        
          
          
          
          
          <li class="nav-item">
            <a class="nav-link" href="/alwaysblog/tags/">标签</a>
          </li>
        
          
          
          
          
          <li class="nav-item">
            <a class="nav-link" href="/alwaysblog/links/">友链</a>
          </li>
        
          
          
          
          
          <li class="nav-item">
            <a class="nav-link" href="/alwaysblog/about/">关于</a>
          </li>
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" data-toggle="modal" data-target="#modalSearch">&nbsp;&nbsp;<i
                class="iconfont icon-search"></i>&nbsp;&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>


</nav>

    <div class="view intro-2 rgba-black-slight" id="background">
      <div class="full-bg-img">
        <div class="mask flex-center">
          <div class="container text-center white-text fadeInUp">
            <span class="h2" id="subtitle">
              
            </span>
            
              <br>
              <p class="mt-3">
                <i class="far fa-calendar-alt"></i>
                <span class="post-date">2021-08-18&nbsp;|&nbsp;</span>
                <i class="far fa-chart-bar"></i>
                <span class="post-count">5.8k</span>字&nbsp;|&nbsp;
                <i class="far fa-clock"></i>
                <span class="post-count">22</span>分钟
                
              </p>
            
          </div>
          
        </div>
      </div>
    </div>
  </header>
  <main id="mainContent" class="rgba-black-slight">
    
      
<meta name="referrer" content="no-referrer" />

<div class="container-fluid">
  <div class="row">
    <div class="d-none d-lg-block col-lg-2"></div>
    <div class="col-lg-8 nopadding-md">
      <div class="py-5 z-depth-3" id="board">
        <div class="post-content mx-auto" id="post">
          <div class="markdown-body">
            <h2 id="性能测试理论知识"><a href="#性能测试理论知识" class="headerlink" title="性能测试理论知识"></a>性能测试理论知识</h2><p><strong>性能测试的目的：发现性能的瓶颈</strong></p>
<h3 id="负载测试"><a href="#负载测试" class="headerlink" title="负载测试"></a>负载测试</h3><pre><code>通过逐步加压的方法，达到既定的性能阀值的目标。
    阀值的设定应是小于等于某个值,如 CPU 的使用率小于等于 80%
</code></pre>
<h3 id="压力测试"><a href="#压力测试" class="headerlink" title="压力测试"></a>压力测试</h3><pre><code>通过逐步加压的方法，使系统的某些资源达到饱和，甚至失效的状态（也就是说什么条件下可以把系统压崩溃）
</code></pre>
<h3 id="并发测试"><a href="#并发测试" class="headerlink" title="并发测试"></a>并发测试</h3><pre><code>同一时间内，多个虚拟用户同时访问同一模块、同一功能。通常的测试方法是设置集合点。
</code></pre>
<h3 id="容量测试"><a href="#容量测试" class="headerlink" title="容量测试"></a>容量测试</h3><pre><code>通常是指数据库层面的，目标是获取数据库最佳容量的能力，又称为容量预估。
    测试方法：在一定的并发用户，不同的基础数据量下，观察数据库的处理能力，即获取数据库的各项性能指标
</code></pre>
<h3 id="可靠性测试（稳定性测试-疲劳测试）"><a href="#可靠性测试（稳定性测试-疲劳测试）" class="headerlink" title="可靠性测试（稳定性测试 / 疲劳测试）"></a>可靠性测试（稳定性测试 / 疲劳测试）</h3><pre><code>系统在高压的情况下，长时间的运行系统是否稳定。
    如 CPU 使用率在 80% 以上，7 * 24 小时运行，系统是否稳定
</code></pre>
<h3 id="异常测试（失败测试）"><a href="#异常测试（失败测试）" class="headerlink" title="异常测试（失败测试）"></a>异常测试（失败测试）</h3><pre><code>指系统架构方面的测试，如：在负载均衡架构中，要测试宕机（死机）、节点挂掉等情况下系统的反应。
</code></pre>
<h3 id="性能测试指标定义"><a href="#性能测试指标定义" class="headerlink" title="性能测试指标定义"></a>性能测试指标定义</h3><ul>
<li>事务</li>
</ul>
<pre><code>从客户端发起的一个或多个请求(这些请求组成一个完整的操作)，到客户端接收到从服务器返回的响应。
</code></pre>
<ul>
<li>TPS (Transactions Per Second)</li>
</ul>
<pre><code>每秒钟系统可以处理的事务数
</code></pre>
<ul>
<li>QPS：(Query per second )</li>
</ul>
<pre><code>一台查询服务器每秒处理的请求次数
</code></pre>
<ul>
<li>请求响应时间</li>
</ul>
<pre><code>从客户端发起的一个请求开始，到客户端接收到从服务器返回的响应。整个过程所耗费的时间
</code></pre>
<ul>
<li>事务响应时间</li>
</ul>
<pre><code>事务可能有一个或多个请求组成，事务的响应时间主要针对于用户的角度而言，如转账。
</code></pre>
<ul>
<li>并发定义</li>
</ul>
<pre><code>没有严格意义上的并发，并发总有先后，无论是差距 1 毫秒或者是 1 微秒，总有一个时间差。所以并发讲的是一个时间范围内，比如 1S 内。
</code></pre>
<ul>
<li>并发用户数</li>
</ul>
<pre><code>同一单位时间内，对系统发起请求的用户数量
</code></pre>
<ul>
<li>吞吐量</li>
</ul>
<pre><code>一次性能测试过程中，网络上传输的数据量的总和
</code></pre>
<ul>
<li>吞吐率</li>
</ul>
<pre><code>单位时间内网络上传输的数据量
吞吐率 = 吞吐量 / 吞吐时间
</code></pre>
<ul>
<li>点击率</li>
</ul>
<pre><code>每秒钟用户向服务器提交的请求数。Web 应用程序特有的指标，
</code></pre>
<ul>
<li>资源使用率</li>
</ul>
<pre><code>对不同的系统资源的使用情况，如： CPU、内存、 IO
</code></pre>
<h3 id="性能测试的监控指标"><a href="#性能测试的监控指标" class="headerlink" title="性能测试的监控指标"></a>性能测试的监控指标</h3><ul>
<li>响应时间</li>
</ul>
<pre><code>反映完成某笔业务（事务）所需要的时间。
在性能测试中通过事务函数来完成对响应时间的统计，事务是指做某件事的操作，
事务函数会记录开始做这件事情和该事情完成之间的时间差（事务响应时间 Transaction Response Time）

    其他：
    1. 响应时间的2、5、8原则
    2. 80/20原则（又称帕累托效应，比如，某些系统一天中80%的访问量集中在20%的时间内）
</code></pre>
<ul>
<li>吞吐量</li>
</ul>
<pre><code>反映单位时间内能够处理的事务数。
在测试工具中，吞吐量也被称为TPS，单位时间内完成的事务数。
TPS = 事务数 / 时间
</code></pre>
<ul>
<li>服务器资源占用</li>
</ul>
<pre><code>服务器资源占用反映在负载下系统的资源利用率。资源的占用率越低，说明系统越优秀，资源是指系统运行的一切软硬件平台。
在性能测试中，我们需要监控系统在负载下的硬件或者软件上的各种资源的使用情况，
如：CPU的占用率、内存使用率、IO等（数据库中的查询Cache命中率）。
对于终端用户来讲，其最关心的指标是响应时间。用户并不关心多少人使用，以及资源是否足够，所以性能测试必须保证在任意情况下终端用户使用的操作响应时间不大于5秒。
</code></pre>
<h3 id="性能测试的原理"><a href="#性能测试的原理" class="headerlink" title="性能测试的原理"></a>性能测试的原理</h3><ul>
<li>用户行为模拟</li>
</ul>
<pre><code>低成本且具有可行性，模拟大量用户操作的一种技术，凭借此项技术将被测系统在测试阶段运行起来，以检测系统工作是否正常。
    1. 通过参数化，实现不同用户使用不同数据 
    1. 通过集合点模拟多用户并发操作
    2. 通过关联实现用户请求间的依赖关系
    3. 通过思考时间代替请求间的延时时间
</code></pre>
<ul>
<li>性能指标监控</li>
</ul>
<pre><code>通过模拟用户行为，在系统运行中需要监控各项性能指标，并分析指标正确性
    1. 请求响应时间（通过事务实现 ）
    2. 服务器处理能力监控（通过事务计算吞吐量）
    3. 服务器资源利用率监控（计数器接口）
</code></pre>
<ul>
<li>性能调优</li>
</ul>
<pre><code>通过指标的监控发现系统存在的性能缺陷，利用分析工具定位并修正性能问题。
</code></pre>
<h2 id="性能测试的工作流程"><a href="#性能测试的工作流程" class="headerlink" title="性能测试的工作流程"></a>性能测试的工作流程</h2><p><img src="https://cdn.nlark.com/yuque/0/2020/png/518310/1598235372090-03e1cf57-25a2-4416-8850-168cf6f21260.png#align=left&display=inline&height=426&margin=%5Bobject%20Object%5D&originHeight=426&originWidth=767&size=0&status=done&style=none&width=767" srcset="undefined"></p>
<h3 id="性能测试的需求分析"><a href="#性能测试的需求分析" class="headerlink" title="性能测试的需求分析"></a>性能测试的需求分析</h3><ul>
<li>目的: 明确测试目标和测试场景</li>
<li>新系统<ul>
<li>同行业比较</li>
<li>业务预期</li>
</ul>
</li>
<li>老系统<ul>
<li>对比以往用户的使用行为以及用户量</li>
</ul>
</li>
<li>性能需求的的提取</li>
</ul>
<pre><code>1. 典型重要业务场景
2. 高频使用场景
3. 存在大量并发业务场景
4. 容易出错的场景
</code></pre>
<h3 id="系统应用分层架构"><a href="#系统应用分层架构" class="headerlink" title="系统应用分层架构"></a>系统应用分层架构</h3><p><img src="https://cdn.nlark.com/yuque/0/2020/png/518310/1598235371396-5205c275-4e4a-4807-985f-4920bfd9bc79.png#align=left&display=inline&height=438&margin=%5Bobject%20Object%5D&originHeight=438&originWidth=832&size=0&status=done&style=none&width=832" srcset="undefined"></p>
<h2 id="JMeter-性能测试"><a href="#JMeter-性能测试" class="headerlink" title="JMeter 性能测试"></a>JMeter 性能测试</h2><h3 id="JMeter-实现逻辑分支控制"><a href="#JMeter-实现逻辑分支控制" class="headerlink" title="JMeter 实现逻辑分支控制"></a>JMeter 实现逻辑分支控制</h3><ul>
<li>逻辑控制器<ul>
<li>用来控制测试脚本的逻辑判断，即控制脚本的运行(以下为常用控制器)</li>
<li>如果（if）控制器</li>
<li>include Controller</li>
<li>Runtime Controller</li>
<li>Switch Controller</li>
<li>While Controller</li>
</ul>
</li>
</ul>
<h3 id="JMeter-实现配置管理"><a href="#JMeter-实现配置管理" class="headerlink" title="JMeter 实现配置管理"></a>JMeter 实现配置管理</h3><ul>
<li>配置元件</li>
</ul>
<h3 id="JMeter-函数助手"><a href="#JMeter-函数助手" class="headerlink" title="JMeter 函数助手"></a>JMeter 函数助手</h3><ul>
<li>_CSVRead: 用于对脚本进行参数话，当脚本中不同变量需要不同参数值时</li>
</ul>
<pre><code>_CSVRead 函数参数说明：

CSV file to get values from | *alias ==&gt; 指$&#123;__CSVRead(,)&#125;中（）内的第一个参数，调用文件logins.txt的路径
Column number of CSV file | next | *alias ==&gt; 指$&#123;__CSVRead(,)&#125;中（）内的第二个参数，调用文件logins.txt中第几列的参数，注意第一列为0，第二列为1，依此类推。。。

生成的函数字符串： $&#123;__CSVRead(C:\Users\234652\Desktop\JMeter\log\01.txt,5)&#125;
[ 使用方法 ]： 配合 配置元件用户定义的变量使用
</code></pre>
<ul>
<li>_Random： 生成随机数</li>
</ul>
<pre><code>_Random 函数参数说明：

    The minimum value allowed for a range of values ==&gt; 一个范围内允许的最小的值   1
    The maximum value allowed for a range of values ==&gt; 一个范围内允许的最大的值   100
    Name of variable in which to store the result (optional) ==&gt; 为生成随机数添加变量名称   id(可任意)

    生成的函数字符串：$&#123;__Random(2,100,)&#125;  ==&gt; id = 55(随机数)
</code></pre>
<ul>
<li>_Log：</li>
</ul>
<pre><code>log 函数参数说明：

    String to be logged (and returned) ==&gt; 日志输出的内容，可以引用变量名称
    Log level (default INFO) or OUT or ERR ==&gt; 定义日志输出的级别，INFO、OUT、warn
    Throwable text (optional) ==&gt; 抛出的异常信息
</code></pre>
<ul>
<li>_Split： 字符串分割函数</li>
</ul>
<h3 id="聚合报告"><a href="#聚合报告" class="headerlink" title="聚合报告"></a>聚合报告</h3><ul>
<li>Label：每个 JMeter 的 element（例如 HTTP Request）都有一个 Name 属性，这里显示的就是 Name 属性的值</li>
<li>#Samples：请求数——表示这次测试中一共发出了多少个请求，如果模拟10个用户，每个用户迭代10次，那么这里显示100</li>
<li>Average：平均响应时间——默认情况下是单个 Request 的平均响应时间，当使用了 Transaction Controller 时，以 Transaction 为单位显示平均响应时间</li>
<li>Median：中位数，也就是 50％ 用户的响应时间</li>
<li>90% Line：90％ 用户的响应时间</li>
<li>Min：最小响应时间</li>
<li>Max：最大响应时间</li>
<li>Error%：错误率 —— 错误请求数 / 请求总数</li>
<li>Throughput：吞吐量——默认情况下表示每秒完成的请求数（Request per Second），当使用了 Transaction Controller 时，也可以表示类似 LoadRunner 的 Transaction per Second 数</li>
<li>KB/Sec：每秒从服务器端接收到的数据量，相当于 LoadRunner 中的 Throughput / Sec</li>
</ul>
<p><strong>重点关注的数据：</strong></p>
<ul>
<li>Samples： 请求数</li>
<li>Average： 平均响应时间</li>
<li>Min： 最小响应时间</li>
<li>Max： 最大响应时间</li>
<li>Error%： 错误率</li>
<li>Throughput： 吞吐量</li>
</ul>
<h3 id="JMeter-扩展组件开发"><a href="#JMeter-扩展组件开发" class="headerlink" title="JMeter 扩展组件开发"></a>JMeter 扩展组件开发</h3><pre><code class="shell">$ Git 地址：
</code></pre>
<h2 id="Linux-服务器监控性能测试"><a href="#Linux-服务器监控性能测试" class="headerlink" title="Linux 服务器监控性能测试"></a>Linux 服务器监控性能测试</h2><h3 id="测试范围及性能指标"><a href="#测试范围及性能指标" class="headerlink" title="测试范围及性能指标"></a>测试范围及性能指标</h3><p><strong>—— —— CPU 内存 磁盘 网络 版本</strong></p>
<h3 id="进程和线程"><a href="#进程和线程" class="headerlink" title="进程和线程"></a>进程和线程</h3><ul>
<li>进程： 具有一定独立功能的程序关于某个数据集合上的一次运行活动，是系统进行资源分配和调度的一个独立单位。（进程是可以独立运行的）</li>
<li>线程： 是进程的一个实体，是 CPU 调度和分派的基本单位他是比进程更小的能够独立运行的基本单位，线程自己基本上不拥有系统资源，只拥有一点在运行中必不可少的资源。一个线程可以创建和撤销另一个线程</li>
</ul>
<h4 id="进程与线程的区别"><a href="#进程与线程的区别" class="headerlink" title="进程与线程的区别"></a>进程与线程的区别</h4><ol>
<li>一个线程只属于一个进程，一个进程中可以拥有多个线程，线程之间可以互相操作。</li>
<li>线程是进程工作的最小单位，</li>
<li>一个进程会分配一个地址空间，进程与进程之间不共享地址空间。即不共享内存。</li>
<li>同一个进程下的不同的多个线程，共享父进程的地址空间。</li>
<li>线程在执行过程中，需要协作同步，不同进程的线程之间要利用消息通信的办法实现同步。</li>
<li>线程作为调度和分派的基本单位，进程作为拥有资源的基本单位</li>
</ol>
<h4 id="进程的优缺点"><a href="#进程的优缺点" class="headerlink" title="进程的优缺点"></a>进程的优缺点</h4><p>[ 优点 ]</p>
<ul>
<li>每个进程互相独立，不影响主程序的稳定性，子进程崩溃不影响其他进程</li>
<li>通过添加 CPU 可以扩充性能</li>
<li>可以尽量减少线程加锁和解锁的影响，极大地提高了性能</li>
</ul>
<p>[ 缺点 ]</p>
<ul>
<li>逻辑控制复杂，需要和主程序交互</li>
<li>多进程调度开销大</li>
</ul>
<h4 id="线程的优缺点"><a href="#线程的优缺点" class="headerlink" title="线程的优缺点"></a>线程的优缺点</h4><p>[ 优点 ]</p>
<ul>
<li>程序的逻辑和控制方式简单</li>
<li>所有线程可以共享内存和变量等</li>
<li>线程方式消耗的总资源比进程方式少</li>
</ul>
<p>[ 缺点 ]</p>
<ul>
<li>线程与主程序共用地址空间，最大内存地址受限</li>
<li>线程之间的同步和加锁不易控制（同步锁）</li>
<li>一个线程的崩溃可能影响整个程序的稳定性</li>
</ul>
<h3 id="Linux-服务器监控命令"><a href="#Linux-服务器监控命令" class="headerlink" title="Linux 服务器监控命令"></a>Linux 服务器监控命令</h3><h4 id="实时监控命令"><a href="#实时监控命令" class="headerlink" title="实时监控命令"></a>实时监控命令</h4><ul>
<li>top (实时监控-综合)<ul>
<li>作用： 实时监控系统的运行状态，并且可以按照 CPU 及内存进行排序</li>
<li>top -h：帮助</li>
<li>top -p: 监控指定进程，当监控多个进程是，进程 ID 以逗号分隔。语法：top -p PID</li>
</ul>
</li>
<li>top 任务区命令(top 进入任务区)<ul>
<li>M：按内存使用率排序</li>
<li>P: 按 CPU 使用率排序</li>
<li>z: 彩色 / 黑白显示</li>
</ul>
</li>
</ul>
<pre><code>load average 说明：

    1. top 中的 load average 表示系统运行队列的平均利用率，也可以认为是可运行进程的平均数
    2. 三个值分别表示： 1 分钟、5 分钟、15 分钟的平均负载值
    3. 在单核 CPU 中 load average 的值为 1 时，表示满负荷状态。
    4. 同理，在多核 CPU 中满负载 load average 的值为 1 * CPU 核数。
</code></pre>
<ul>
<li>vmstat（实时监控 - 综合）<ul>
<li>功能：可以监控操作系统的进程状态、内存、虚拟内存、磁盘 IO、CPU 的信息</li>
<li>选项：vmstat -S 使用指定单位显示，（k, K, m, M 分别代表 1000, 1024, 1000000, 1048576 字节，默认单位 K 1024）</li>
<li>语法：vmstat 2 5 （2 表示时间间隔； 5 表示 显示次数）</li>
</ul>
</li>
<li>free (实时监控-内存)<ul>
<li>功能：监控系统内存的使用状态</li>
<li>语法：free -h</li>
</ul>
</li>
</ul>
<pre><code>free - h 显示字段说明：

    1. total： 总物理内存的大小
    2. Used： 已经使用多大
    3. Free: 可用多少
    4. shared: 多个进程共享的内存总额
    5. buffers/cached: 磁盘缓存的大小
</code></pre>
<ul>
<li>mpstat（实时监控 - CPU）<ul>
<li>功能：可以查看多核心 CPU 中每个计算核心的统计数据</li>
<li>参数：无参数时，显示系统启动以后所有信息的平均值，有 interval 时，第一行的信息自系统启动以来的平均信息，从第二行开始，输出为前一个 interval 时间段的平均信息</li>
<li>语法：mpstat [-P | ALL] [interval | count]</li>
</ul>
</li>
</ul>
<pre><code>mpstat 语法使用说明

    1. -P: 表示监控那个 CPU ;在 [0, CPU 个数减一] 中取值
    使用方法：mpstat -P 0（实时监控第一个 CPU）; mpstat -P 2(实时监控第三个 CPU);
    2. interval 相邻两次采样的间隔事件; count 采样的次数，count 只能和 delay 一起使用
    使用方法：mpstat 2 5 （2 表示时间间隔； 5 表示 显示次数）
</code></pre>
<ul>
<li>netstat (实时监控 - 网络) （netstat -ntlp 查看端口有没有被监听）<ul>
<li>netstat -n 拒绝显示别名，能显示数字的全部显示数字</li>
<li>netstat -l 仅列出有在 Listen（监听）的服务状态</li>
<li>netstat -p 显示建立相关链接的程序名</li>
<li>netstat -t 显示 TCP 相关选项</li>
<li>netstat -u 仅显示 UDP 相关选项</li>
<li>netstat -i 显示自动匹配接口的信息 ==&gt; 查看网络传输的大小以及有没有发生错误</li>
<li>netstat -c 每隔一个固定时间，执行该 netstat 命令</li>
</ul>
</li>
<li>iostat (实时监控 - 磁盘)<ul>
<li>作用： 显示磁盘读写操作的统计信息，同时给出 CPU 的使用情况</li>
<li>iostat -x [设备名称] 1 2 输出指定要统计的磁盘设备名称，默认为所有磁盘设备（1，表示间隔时间，2 表示执行次数）</li>
</ul>
</li>
</ul>
<pre><code class="shell">[root@dahuatech ~]# iostat -x
    Linux 2.6.32-573.el6.x86_64 (dahuatech)         07/28/2020      _x86_64_        (8 CPU)

    avg-cpu:  %user   %nice %system %iowait  %steal   %idle
    15.64    0.15   14.30    0.48    0.00   69.43

    Device:         rrqm/s   wrqm/s     r/s     w/s   rsec/s   wsec/s avgrq-sz avgqu-sz   await  svctm  %util
    sda               0.60   241.21    0.68   14.04    64.67  2041.76   143.15     0.09    6.17   1.37   2.01
    dm-0              0.00     0.00    0.55    1.49     4.39    11.91     8.00     0.01    5.44   0.34   0.07
    dm-1              0.00     0.00    0.00    0.00     0.01     0.00     7.94     0.00    3.88   1.21   0.00
    dm-2              0.00     0.00    0.01  152.33     0.07  1218.60     8.00     1.56   10.24   0.03   0.39
    dm-3              0.00     0.00    0.17    0.00    27.40     0.00   159.85     0.00    1.91   1.45   0.02
    dm-4              0.00     0.00    0.16   97.30     9.72   778.39     8.09     0.26    2.69   0.08   0.77

    重点关注： r/s 、w/s、 %util(繁忙程度)

    &gt;&gt; 将命令结果以二进制格式存放在文件中
</code></pre>
<ul>
<li>sar 万能命令<ul>
<li>功能：linux 全面的系统性能分析工具之一，可以从多方面对系统的活动进行报告</li>
<li>监控范围： 文件读写情况、系统调用的使用情况、磁盘 I/O 、CPU 效率、内存使用情况、进程活动、IPC 有关的活动</li>
<li>语法：sar [options] [-O file] t n ==&gt; (options: 命令行选项 t：表示采样间隔时间（必有）；n：表示采样次数（可选，默认 1); -o file: 表示将命令结果以二进制格式存放在文件中，file 表示文件名)</li>
</ul>
</li>
</ul>
<pre><code class="shell">options 选项： 
    -A: 所有报告的总和； 
    -u: CPU 利用率； 
    -v: 进程、节点、文件和锁表的状态； 
    -r：显示系统内存的使用情况
    -B: 内存分页情况
    -b: 缓冲区使用情况（8 份区域）
</code></pre>
<h4 id="进程追踪命令"><a href="#进程追踪命令" class="headerlink" title="进程追踪命令"></a>进程追踪命令</h4><ul>
<li>strace<ul>
<li>功能：集诊断、调试、统计于一体的工具，追踪进程的运行过程</li>
<li>选项 -p： 跟踪指定进程</li>
<li>选项 -f: 跟踪由 fork 子进程系统调用</li>
<li>选项 -c: 统计每一系统调用的所执行的时间，次数和出错的次数等</li>
<li>选项 -t: 在输出中的每一行前加上时间信息， -tt 时间确定到微秒级</li>
<li>选项 -e expr: 输出过滤器，通过表达式，可以过滤掉不想要的输出</li>
<li>选项 -o filename: 默认将结果输出到 stdout,通过 -o 输出到指定文件夹</li>
</ul>
</li>
</ul>
<h4 id="监控工具-nmon"><a href="#监控工具-nmon" class="headerlink" title="监控工具 nmon"></a>监控工具 nmon</h4><pre><code>说明：
下载：
    wget
</code></pre>
<h2 id="数据驱动性能测试"><a href="#数据驱动性能测试" class="headerlink" title="数据驱动性能测试"></a>数据驱动性能测试</h2><pre><code>定义：从数据文件中读取测试数据，驱动测试过程的一种测试方法（更高级的参数化）。
特点：
    1. 测试数据与测试代码分离
    2. 数据控制过程
    3. 可以减少测试代码量
    4. 降低脚本开发和维护的成本
    5. 便于用例的修改和维护
要求：
    1. 较强的代码能力
    2. 较强的分层架构设计思维
    3. 对开发框架有一定的了解
使用场景：
     1. 复杂的业务流程
    2. 根据业务场景分流
    3. 符合条件的并发场景
</code></pre>
<h2 id="数据库的架构设计"><a href="#数据库的架构设计" class="headerlink" title="数据库的架构设计"></a>数据库的架构设计</h2><h3 id="数据库性能测试"><a href="#数据库性能测试" class="headerlink" title="数据库性能测试"></a>数据库性能测试</h3><ul>
<li>测试范围</li>
</ul>
<pre><code>1. SQL 语句   =&gt; 慢查询等
2. 资源使用率
3. 数据库架构的合理性
4. 数据库的性能指标
</code></pre>
<h3 id="数据库架构"><a href="#数据库架构" class="headerlink" title="数据库架构"></a>数据库架构</h3><ul>
<li>一主多从</li>
</ul>
<pre><code>读写分离：
    master(主写，主库)
    ==&gt;复制 slave(从读，从库)
    ==&gt;复制 slave(从读，从库)
缺点： 主从延迟
</code></pre>
<ul>
<li>双机热备</li>
</ul>
<pre><code>KeepAlived
    ==&gt; VIP (虚拟 IP)
    ==&gt; master  ==&gt; 复制 ==&gt; slave
缺点：
优点：
</code></pre>
<h3 id="数据库主从同步的工作原理"><a href="#数据库主从同步的工作原理" class="headerlink" title="数据库主从同步的工作原理"></a>数据库主从同步的工作原理</h3><pre><code>1. master 将改变记录到二进制（binary log 文件）中
2. slave 将 master 的 binary log events 拷贝到它的中继日志（relay log，转换日志）
3. slave 重做中继日志中的事件，将改变反映他自己的数据
</code></pre>
<h3 id="数据库分库分表的设计方法"><a href="#数据库分库分表的设计方法" class="headerlink" title="数据库分库分表的设计方法"></a>数据库分库分表的设计方法</h3><pre><code>分库分表原因：
    1. 单表或库数据量太大
    2. 硬件不能升级或无法升级
方案：
    1. 业务拆分（用户、商品、订单、 ... ...）
    2. 垂直拆分（商品 ==&gt; 电子商品、母婴商品、 ... ...）
    3. 水平拆分(一致性哈西算法)
    usreid  ==&gt; userid%3 == 1
            ==&gt; userid%3 == 2
            ==&gt; userid%3 == 3
</code></pre>
<h2 id="数据库性能测试-1"><a href="#数据库性能测试-1" class="headerlink" title="数据库性能测试"></a>数据库性能测试</h2><h3 id="MySQL"><a href="#MySQL" class="headerlink" title="MySQL"></a>MySQL</h3><ul>
<li>MariaDB(主流分支)<ul>
<li>MySQL 之父 Widenius 创建，目标在于替换现有的 MySQL</li>
<li>兼容 MySQL, 对于开发者来说感知不到变化</li>
<li>MariaDB is free and open source software</li>
</ul>
</li>
</ul>
<h3 id="MySQL-数据库监控指标"><a href="#MySQL-数据库监控指标" class="headerlink" title="MySQL 数据库监控指标"></a>MySQL 数据库监控指标</h3><ul>
<li>QPS(Queries per seconds)<ul>
<li>每秒钟查询数量</li>
<li>show global status like ‘Question%’;</li>
</ul>
</li>
<li>TPS (Transactions Per Second) TPS = Com_commit + Com_rollback) / seconds<ul>
<li>show global status like ‘Com_commit’;</li>
<li>show global status like ‘Com_rollback’;</li>
</ul>
</li>
<li>线程连接数<ul>
<li>show global status like ‘Max_used_connections’;(使用的最大连接数)</li>
<li>show global status like ‘Max_connections’;(设置的最大连接数)</li>
<li>show global status like ‘Threads%’;</li>
</ul>
</li>
<li>Query Cache<ul>
<li>查询缓存，用于缓存 select 查询结果</li>
<li>当下次接收到相同查询请求时，不在执行实际查询处理而直接返回结果</li>
<li>适用于大量查询，很少改变表中的数据</li>
</ul>
</li>
<li>Query Cache 命中率（MySQL 特有）<ul>
<li>show global status like ‘Qcache%’;</li>
<li>命中率计算：Query_cache_hits = (Qcahce_hits/(Qcahce_hits + Qcahce_inserts)) * 100%</li>
</ul>
</li>
</ul>
<pre><code>开启：
1. 修改 my.cnf 文件
2. 将 query_cache_size 设置为具体的大小（取决于查询的实际情况，最好设置为 1024 的倍数，参考值 32M）
3. 增加一行: query_cache_type = 0/1/2
    =&gt; 1 表示缓存所有结果，除非你的 select 语句使用 SQL_NO_CACHE 禁用了查询缓存
    =&gt; 2 表示只缓存在 select 语句中通过 SQL_CACHE 指定需要缓存的查询
</code></pre>
<ul>
<li>锁定状态<ul>
<li>show global status like ‘%lock’;</li>
<li>table_locks_waited / table_lockks_immediate 值越大代表表锁造成的阻塞越严重</li>
<li>innodb_row_lock_waits innodb 行锁,太大可能是间隙锁造成的</li>
<li>表锁、行锁、间隙锁</li>
</ul>
</li>
<li>主从延时<ul>
<li>查询主从延时时间： show slave status</li>
</ul>
</li>
</ul>
<h3 id="MySQL-慢查询工作原理及操作"><a href="#MySQL-慢查询工作原理及操作" class="headerlink" title="MySQL 慢查询工作原理及操作"></a>MySQL 慢查询工作原理及操作</h3><pre><code>慢查询：
    1. 执行速度超过定义的时间的查询
    2. 不同系统定义不同的慢查询指标
慢查询开启：
    1. 编辑 etc/my.cnf 在 [mysqlid] 域中添加：
    slow_query_log = 1 (开启慢查询)
    2. 设置慢查询日志路径：
    slow_query_log_file = /data/mysql/slow.log
    3. 设置慢查询的时长
    long_query_time = 1
    4. 未使用索引的查询也被记录到慢查询日志中
    log_queries_not_using_indexes = 1
</code></pre>
<ul>
<li>慢查询日志分析<ul>
<li>mysqldumpslow 命令</li>
<li>-s : 表示按照何种方式排序</li>
<li>-t : top n 的意思，即返回前面多少条数据</li>
<li>-g : 后边可写正则匹配模式，大小写不敏感</li>
</ul>
</li>
<li>mysqldumpslow -s 的更多参数<ul>
<li>c 访问计数</li>
<li>i 锁定时间</li>
<li>r 返回记录</li>
<li>t 查询时间</li>
<li>al 平均锁定时间</li>
<li>ar 平均返回记录数</li>
<li>at 平均查询时间</li>
</ul>
</li>
</ul>
<pre><code>使用：
    1. 得到返回记录集最多的 10 个 SQL
        mysqldumpslow -s r -t 10 slow.log
    2. 得到访问次数最多最多的 10 个 SQL
        mysqldumpslow -s c -t 10 slow.log
    3. 得到按照时间排序的前 10 条里面含有左连接的查询语句
        mysqldumpslow -s t -t 10 -g &quot;left join&quot; slow.log
</code></pre>
<ul>
<li>SQL 语句性能分析<ul>
<li>explain select 语句</li>
</ul>
</li>
</ul>
<pre><code class="markdown">explain 返回结果分析
    1. ID： select 识别符，代表语句的执行顺序，id 数字越大越先执行，如果一样大，从上往下执行
    2. select_type: 
    3. table: 显示查询表名，&lt;derived N&gt; 临时表
    **4. type: **
        1) 依次从好到差：**system, const, eq_ref,** ref, fulltext, ref_or_null, unique_subquery, index_subquery, range, **index_merge, index, all**
        2) 除了 all, 其他 type 都可以使用到索引，除了 index_merge（表示查询使用两个以上的索引）, 其他 type 只可以用到一个索引
    5. possible_keys: 可能使用的索引
    6. key: 真正使用到的索引
    7. key_len: 
    8. ref:
    9. rows: 估算的扫描行数
    10. extra:
</code></pre>
<h3 id="MySQL-索引的概念及作用"><a href="#MySQL-索引的概念及作用" class="headerlink" title="MySQL 索引的概念及作用"></a>MySQL 索引的概念及作用</h3><p>[ 索引类型 ]</p>
<ul>
<li>主键索引（唯一索引，不允许有空值）</li>
<li>全文索引（fulltext, MyISAM 表特有）</li>
<li>唯一索引（值唯一，允许有空值）</li>
<li>组合索引（多列索引，多列同时创建索引）</li>
<li>普通索引（无限制）</li>
</ul>
<p>[ 索引创建规则 ]</p>
<ul>
<li>可以提高查询速度，但是减低插入和更新的速度，并占用磁盘空间</li>
<li>在插入与更新数据时，要重写索引文件</li>
<li>单张表索引数量最好不超过 5 个</li>
<li>单个索引中的字段数不超过 5 个（组合索引）</li>
<li>不适用索引的查询： like 模糊查询；反向查询，not in / not like</li>
</ul>
<h3 id="MySQL-存储引擎"><a href="#MySQL-存储引擎" class="headerlink" title="MySQL 存储引擎"></a>MySQL 存储引擎</h3><ul>
<li>MyISAM（只支持表锁）</li>
</ul>
<pre><code>优点：
    1. 读取性能比 innoDB 高
    2. 索引与数据分离，使用压缩，从而提高了内存使用率
缺点：
    1. 不支持事务
    2. 写入数据时，直接锁表（表锁）
</code></pre>
<ul>
<li>InnoDB</li>
</ul>
<pre><code>优点：
    1. 支持事务 
    2. 支持外键
    3. 支持行锁
缺点：
    1. 不支持 全文索引
    2. 行锁并不绝对，当不确定扫描范围时，锁全表
    3. 索引与数据捆绑，没有使用压缩，导致体积庞大
</code></pre>
<h3 id="MySQL-实时监控"><a href="#MySQL-实时监控" class="headerlink" title="MySQL 实时监控"></a>MySQL 实时监控</h3><ul>
<li>orzdba(监控工具)</li>
</ul>
<pre><code>./orzdba 执行
使用：
</code></pre>
<h3 id="MySQL-集群监控方案-天兔-LEPUS"><a href="#MySQL-集群监控方案-天兔-LEPUS" class="headerlink" title="MySQL 集群监控方案 - 天兔 LEPUS"></a>MySQL 集群监控方案 - 天兔 LEPUS</h3><ul>
<li>天兔 LEPUS 全部数据库实例监控</li>
</ul>
<pre><code>本地部署： 产品 &gt; 文档中心 &gt; 安装
    admin /Lepusadmin
</code></pre>
<h3 id="MySQL-性能测试的用例准备"><a href="#MySQL-性能测试的用例准备" class="headerlink" title="MySQL 性能测试的用例准备"></a>MySQL 性能测试的用例准备</h3><pre><code>要点：使用 sql 模拟用户使用场景(增删改查语句)
工具：JMeter
步骤： 
    1. JDBC Connection Configuration 配置 MySQL
        Database URL:  jdbc:mysql://192.168.1.7:3306/test
        Driver class:  com.mysql.cj.jdbc.Driver
        Username:
        Password:
    2. JDBC Request 写 SQL 脚本
        select * fom user
</code></pre>

            <hr>
          </div>
          <br>
          <div>
            <div id="post-tag">
              
                <span>
                  <i class="iconfont icon-inbox"></i>
                  
                    <a class="hover-with-bg" href="/categories/%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95">软件测试</a>
                    &nbsp;
                  
                    <a class="hover-with-bg" href="/categories/%E6%80%A7%E8%83%BD%E6%B5%8B%E8%AF%95">性能测试</a>
                    &nbsp;
                  
                </span>
              
              <span>
                <i class="iconfont icon-tag"></i>
                
                  <a class="hover-with-bg" href="/tags/%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95">软件测试</a>
                
                  <a class="hover-with-bg" href="/tags/%E6%80%A7%E8%83%BD%E6%B5%8B%E8%AF%95">性能测试</a>
                
              </span>
            </div>
            
              <div id="post-note">
                <div><strong>本文作者：</strong><a href="/alwaysblog/">张小剩</a></div>
                <div><strong>本文链接：</strong><a href="https://github.com/alwayscn/alwaysblog/post/3113662073/">https://github.com/alwayscn/alwaysblog/post/3113662073/</a></div>
                <div><strong>版权声明：</strong>本站文章除特别声明外，均采用 <a target="_blank" href="https://creativecommons.org/licenses/by-sa/3.0/deed.zh" rel="nofollow noopener noopener">CC BY-NC-SA 3.0 CN</a> 协议进行许可</div>
              </div>
            
            
              <div id="post-nav" class="container">
                  <div class="row">
                    
                      <a href="/alwaysblog/post/519960898/" id="post-nav-prev" class="col">
                        <i class="fas fa-arrow-left"></i>
                        <span class="post-nav-title">Locust 性能测试</span>
                      </a>
                    
                    
                      <a href="/alwaysblog/post/3888393026/" id="post-nav-next" class="col">
                        <span class="post-nav-title">Robot Framework</span>
                        <i class="fas fa-arrow-right"></i>
                      </a>
                    
                  </div>
                </div>
            
          </div>
        </div>

        <!-- custom -->
        

        <!-- Comments -->
        <div class="col-lg-10 mx-auto nopadding-md">
          <div class="comments mx-auto" id="comments">
            
             <br><br>
              
              
  <style type="text/css">
    .v[data-class=v] .vcontent > p > a:not(.at) {
      overflow-wrap: anywhere;
      display: inline;
    }
  </style>
  <div id="vcomments" style="margin: 0 auto;"></div>
  <script defer src="//cdn.jsdelivr.net/npm/@waline/client@latest/dist/Waline.min.js"></script>
<!--   <script defer src="//unpkg.zhimg.com/@waline/client@latest/dist/Waline.min.js"></script> -->
  <script>
    var notify = 'true' == true ? true : false;
    var verify = 'true' == true ? true : false;
    var oldLoad = window.onload;
    window.onload = function () {
      // 设置自定义文字
      const locale = {
        placeholder: "说点什么吧quq",
        uploading: "上传中...默认图床在境内可能无法访问"
      };
      Waline({
        el: '#vcomments',
        serverURL: "https://blog-waline-m0eiqctad-alwayscn.vercel.app/",
        avatar: "mp",
        avatarCDN: "https://gravatar.loli.net/avatar/",
        meta: ['nick', 'mail', 'link'],
        pageSize: "10",
        // 设置 emoji
        emoji: [
          'https://cdn.jsdelivr.net/gh/walinejs/emojis@1.0.0/alus',
          'https://cdn.jsdelivr.net/gh/walinejs/emojis@1.0.0/weibo',
          'https://cdn.jsdelivr.net/gh/walinejs/emojis@1.0.0/tieba',
        ],
        // 设置自定义文字
        locale,

        // 图片上传函数
         uploadImage: false
        // uploadImage: function (file) {
        // return smms(file)
        //         }
      });
      oldLoad && oldLoad();
      // smms 图床，Authorization 的位置为 smms 图床的 token（可选）
      function smms(file) {
        const formData = new FormData();
        formData.append('smfile', file);
        formData.append('format', 'json');
        let data = fetch('https://smms.pvq.workers.dev/upload', {
          method: 'POST',
          mode: 'cors',
          headers: new Headers({
            'Authorization': 'FNnpntzeJnw1SQc61jL6Tt1UZPzmhLBT'
          }),
          body: formData
        }).then(
          res => res.json()
        ).then(function(response) {
          const checkUrl = new RegExp('^[a-zA-z]+://[^\s]*');
          let url = response.code == 'image_repeated' ? response.images : (response.data.url ? response.data.url : '');
          // 若 smms 图床调用失败则转发请求到遇见图床
          return checkUrl.test(url) ? url : hualigs(file);
        }).catch(function(error) {
          // smms 图床调用失败，尝试遇见图床
          return hualigs(file);
        });
        return data;
      }
      // 遇见图床
      function hualigs(file){
        const formData = new FormData();
        formData.append('image', file);
        formData.append('privateStorage', 'backblaze');
        formData.append('apiType', 'catbox');
        formData.append('token', '146faa57355f01c8eed8a045eda6a684');
        return fetch('//www.hualigs.cn/api/upload', {
          method: 'POST',
          mode: 'cors',
          body: formData
        }).then(
          res => res.json()
        ).then(function(response) {
          const checkUrl = new RegExp('^[a-zA-z]+://[^\s]*');
          let backblaze = response.data.url.private.backblaze;
          let catbox = 'https://avatar.75cdn.workers.dev/?url=' + encodeURIComponent(response.data.url.catbox);
          return checkUrl.test(backblaze) ? backblaze : catbox
        });
      }
    };
  </script>
  <noscript>Please enable JavaScript to view the <a target="_blank" href="https://waline.js.org" rel="nofollow noopener noopener">comments
      powered by Waline.</a></noscript>


            
          </div>
        </div>

      </div>
    </div>
<!--     <div class="d-none d-lg-block col-lg-2 toc-container"> -->
    <div id="toc-container" class="d-none d-lg-block col-lg-2 ">
      
  <div id="toc">
    <p class="h4"><i class="far fa-list-alt"></i>&nbsp;目录</p>
    <div id="tocbot"></div>
    <div class="catalog-close" onclick="close_show(0)">关闭</div>
    <div id="post-catalog-bar" onclick="close_show(1)" class="post-catalog-bar-left-minborder" style="left: 144px;">
       <i class="far fa-book-open" style="font-size: 10px"></i> 目 录
    </div>
  </div>


    </div>
  </div>
</div>





    
  </main>
  
<div id="sidebar" class="sidebar-hide">
  <span class="sidebar-button sidebar-button-shift" id="toggle-sidebar" >
    <i class="fa fa-arrow-right on" aria-hidden="true"></i>
  </span>
  <div class="sidebar-overlay"></div>
  <div class="sidebar-intrude">
    <div class="sidebar-avatar">
      <img src="/alwaysblog/static/images/avatar.jpg" srcset="/alwaysblog/static/images/avatar.jpg" alt="avatar"/>
    </div>
    <div class="text-center sidebar-about">
      <p class="h3 sidebar-author">张小剩</p>
      <p class="sidebar-subtitle">One two one ... <script type='text/javascript'>console.log('博主认证: https://bbs.liyuans.com')</script></p>
      
        <a href="https://github.com/alwayscn" class="h4" target="_blank">
          <i class="fab fa-github" aria-hidden="true"></i>
        </a>
        &nbsp;&nbsp;
      
        <a href="https://www.yuque.com/extime/blog" class="h4" target="_blank">
          <i class="fab fa-twitter" aria-hidden="true"></i>
        </a>
        &nbsp;&nbsp;
      
        <a href="https://www.cnblogs.com/wehome" class="h4" target="_blank">
          <i class="fab fa-blog" aria-hidden="true"></i>
        </a>
        &nbsp;&nbsp;
      
        <a href="mailto:zhangxy.cn@gmail.com" class="h4" target="_blank">
          <i class="fas fa-envelope" aria-hidden="true"></i>
        </a>
        &nbsp;&nbsp;
      
    </div>
    <div class="sidebar-friend">
<!--       <p class="h6 sidebar-friend-title"> -->
<!--         <span class="sidebar-label-left"><i class="fas fa-user-friends"></i></span> -->
<!--         <span class="sidebar-label">友情链接</span> -->
<!--       </p> -->
      <ul class="list-group">
        
          <a href="https://console.leancloud.app/" target="_blank">
            <li class="list-group-item">
              <i class="fas fa-quote-left"></i>&nbsp;
              LeanCloud
            </li>
          </a>
        
          <a href="https://vercel.com/" target="_blank">
            <li class="list-group-item">
              <i class="fas fa-quote-left"></i>&nbsp;
              Vercel
            </li>
          </a>
        
          <a href="https://hitokoto.cn/" target="_blank">
            <li class="list-group-item">
              <i class="fas fa-quote-left"></i>&nbsp;
              一言
            </li>
          </a>
        
          <a href="https://zty.pe/" target="_blank">
            <li class="list-group-item">
              <i class="fas fa-quote-left"></i>&nbsp;
              打字游戏
            </li>
          </a>
        
          <a href="https://flipanim.com/" target="_blank">
            <li class="list-group-item">
              <i class="fas fa-quote-left"></i>&nbsp;
              在线涂鸦
            </li>
          </a>
        
          <a href="http://gogoame.sumbioun.com/" target="_blank">
            <li class="list-group-item">
              <i class="fas fa-quote-left"></i>&nbsp;
              Gogoame (午後雨)
            </li>
          </a>
        
          <a href="https://hin.cool/c/dd.html" target="_blank">
            <li class="list-group-item">
              <i class="fas fa-quote-left"></i>&nbsp;
              减压滑碟
            </li>
          </a>
        
          <a href="https://www.jq22.com/yanshi4710" target="_blank">
            <li class="list-group-item">
              <i class="fas fa-quote-left"></i>&nbsp;
              元素周期
            </li>
          </a>
        
    </ul>
    </div>
  </div>
</div>


  
    <a class="z-depth-1" id="scroll-top-button" href="#" role="button">
      <i class="fa fa-chevron-up scroll-top-arrow" aria-hidden="true"></i>
    </a>
  
  
    <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v"
                 for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>
  
  <div id="footerContent"  class="rgba-black-slight">
<footer>
  <div class="footer-plane">
      <div class="blog_music">
        <script src="//music.clwl.online/Player/player.min.js" id="SinKingMusic" key="765"></script>
      </div>
      <div class="footer-container">

        <div class="footer-left">
            <div>
            <!-- 版权信息 -->
            
            <div class="footer-info">
                
                  Copyright © 2023&nbsp;张小剩.Powered by
                 <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener noreferrer">
                  Fluid
                 </a>
                
            </div>
            
            <!-- 备案信息 -->
            
            </div>

        </div>
        <div class="footer-details footer-right">
            <div>
                
                <div class="footer-aside-box">
                    <i class="fa fa-cog fa-spin"></i>
                    <span id="span">本站已稳定运行: 128天11小时56分5秒</span>
                    <script type="text/javascript">
                        function runtime() {
                            // 初始时间，日/月/年 时:分:秒
                            // X = new Date("09/27/2021 07:21:00");
                            console.log("12/12/2021 07:21:00")
                            X = new Date("12/12/2021 07:21:00");
                            Y = new Date();
                            T = (Y.getTime() - X.getTime());
                            M = 24 * 60 * 60 * 1000;
                            a = T / M;
                            A = Math.floor(a);
                            b = (a - A) * 24;
                            B = Math.floor(b);
                            c = (b - B) * 60;
                            C = Math.floor((b - B) * 60);
                            D = Math.floor((c - C) * 60);
                            //信息写入到DIV中
                            span.innerHTML = "本站已稳定运行: " + A + " 天" + B + " 小时" + C + " 分" + D
                             + " 秒"
                        }

                        setInterval(runtime, 1000);
                    </script>
                </div>
                

                
            </div>
      </div>
      </div>
      <!-- 一言 -->
      
          <div class="footer-hitokoto">
            <a id="hitokotoa" href="#" target="_blank" rel="nofollow noopener noreferrer">
              <span id="hitokoto"></span>
            </a>
          </div>
      
  </div>
</footer>
</div>
<!-- SCRIPTS -->
<script src="/alwaysblog/lib/popper/popper.min.js" ></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/js/bootstrap.min.js" ></script>
<script src="https://cdn.staticfile.org/mdbootstrap/4.8.7/js/mdb.min.js" ></script>
<script src="/alwaysblog/js/main.js" ></script>

  <script src="/alwaysblog/js/lazyload.js" ></script>


  
    <script src="https://cdn.staticfile.org/tocbot/4.8.1/tocbot.min.js" ></script>
  
  <script src="/alwaysblog/js/post.js" ></script>

<!-- Plugins -->

  <script src="/alwaysblog/lib/prettify/prettify.min.js" ></script>
  <script type="text/javascript">
    $(document).ready(function () {
      $('pre').addClass('prettyprint  linenums');
      prettyPrint();
    })
  </script>


  <script src="https://cdn.staticfile.org/typed.js/2.0.9/typed.min.js" ></script>
  <script type="text/javascript">
    var typed = new Typed('#subtitle', {
      strings: [
        '  ',
        "性能测试基础&nbsp;",
      ],
      cursorChar: "_",
      typeSpeed: 70,
      loop: false,
    });
    typed.stop();
    $(document).ready(function () {
      $(".typed-cursor").addClass("h2");
      typed.start();
    });
  </script>


  <script src="https://cdn.staticfile.org/anchor-js/4.2.0/anchor.min.js" ></script>
  <script type="text/javascript">
    anchors.options = {
      placement: "right",
      visible: "hover",
      
    };
    var el = "h1,h2,h3,h4,h5,h6".split(",");
    var res = [];
    for (item of el) {
      res.push(".markdown-body > " + item)
    }
    anchors.add(res.join(", "))
  </script>


  <script src="/alwaysblog/js/local-search.js" ></script>
  <script type="text/javascript">
    var path = "/alwaysblog/local-search.xml";
    var inputArea = document.querySelector("#local-search-input");
    inputArea.onclick = function () {
      getSearchFile(path);
      this.onclick = null
    }
  </script>


  <script src="https://cdn.staticfile.org/fancybox/3.5.7/jquery.fancybox.min.js" ></script>
  <script type="text/javascript">
  /* Fancybox */
  var setupFancybox = function () {
    $("#post img:not(.no-zoom img, img[no-zoom])").each(function() {
    var element = document.createElement("a");
      $(element).attr("data-fancybox", "gallery");
      $(element).attr("href", $(this).attr("src"));
      $(this).wrap(element);
    });
  };
  setupFancybox();
  </script>


  

  
    <!-- MathJax -->
    <script type="text/x-mathjax-config">
      MathJax.Hub.Config({
          tex2jax: {
              inlineMath: [ ['$','$'], ["\\(","\\)"]  ],
              processEscapes: true,
              skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
          }
      });

      MathJax.Hub.Queue(function() {
          var all = MathJax.Hub.getAllJax(), i;
          for(i=0; i < all.length; i += 1) {
              all[i].SourceElement().parentNode.className += ' has-jax';
          }
      });

    </script>

    <script src="https://cdn.staticfile.org/mathjax/2.7.6/MathJax.js?config=TeX-MML-AM_CHTML" ></script>

  





  <script type="text/javascript">
  /*一言API*/
  $(document).ready(function(){getHitokoto();});
  function hitokoto(e) {
    $("#hitokoto").stop().fadeOut(function() {
      $("#hitokoto").html(e.hitokoto);
      var element = document.getElementById('hitokotoa');
      element.href = "https://hitokoto.cn/?uuid=" + e.uuid;
      $("#hitokoto").stop().fadeIn();
    })
  };
  function getHitokoto() {
    var e = ["a", "b", "c", "d", "e", "i"];
    fetch('https://v1.hitokoto.cn/?encode=json&charset=utf-8&c=' + e[Math.floor(Math.random() * e.length)], {cache: 'no-cache', method: 'GET', mode: 'cors'}).then(response => response.json()).then(data => {
      hitokoto(data);
      setTimeout(getHitokoto, 1e4);
    }).catch(console.error)
  };
  </script>




<!-- Functions -->
<script type="text/javascript">
  /* 切换背景 */
  
  $("#background").removeClass("banner-bg");
  $("body").addClass("banner-bg");
  var postToTopHight = $("#board").offset().top;
  $(window).scroll(function () {
    var bgDisplay = false;
    var scrollHeight = document.body.scrollTop + document.documentElement.scrollTop;
    bgDisplay = scrollHeight >= postToTopHight;
    if(bgDisplay) {
      $('#background').removeClass("rgba-black-slight");
      $('#mainContent').removeClass("rgba-black-slight");
      $('#footerContent').removeClass("rgba-black-slight");
    } else {
      $('#background').addClass("rgba-black-slight");
      $('#mainContent').addClass("rgba-black-slight");
      $('#footerContent').addClass("rgba-black-slight");
    }
  });
  
</script>

  <script type="text/javascript">
    /*显示博客运行时间*/
    var blogRunTime = function () {
      var runTime = document.getElementById("runtime");
      var runtimeDate = "12/12/2021 07:21:00";
	    var createDate = new Date(runtimeDate);
	    var nowDate = new Date();
	    var dateLine = nowDate.getTime() - createDate.getTime();
	    var runDate = Math.floor(dateLine / (1000 * 60 * 60 * 24));
	    runTime.innerHTML = runDate;
    };
    $(document).ready(function(){
	    blogRunTime();
    });
  </script>


  <script type="text/javascript">
    /*窗口监视*/
    var originalTitle = document.title;
    window.onblur = function(){document.title = "你不爱我了QAQ"};
    window.onfocus = function(){document.title = originalTitle};
  </script>


  <script type="text/javascript">
    /* 雪花效果 */
    console.log('雪花效果 code by kvv.me');
    ~function () {
      function t() {
          e.width = window.innerWidth,
          e.height = window.innerHeight,
          o = Math.round(window.innerWidth * window.innerHeight / 1e4)
      }
      function n() {
          var t = window.innerWidth
            , d = window.innerHeight
            , c = e.getContext("2d");
          c.clearRect(0, 0, t, d),
          c.fillStyle = "rgba(255, 255, 255, 0.7)",
          c.beginPath(),
          a += .01;
          for (var u = 0; o > u; u++) {
            var l = r[u];
            if (!l) {
              continue
            }
            ;c.moveTo(l.x, l.y),
            c.arc(l.x, l.y, l.radius, 0, 2 * Math.PI, !0),
            l.y += Math.cos(a) + l.radius / 2,
            l.x += Math.sin(a * l.direction),
            (l.x > t + 5 || -5 > l.x || l.y > d) && (u % 3 > 0 ? (r[u].x = Math.random() * t,
            r[u].y = -10) : Math.sin(a * l.direction) > 0 ? (r[u].x = -5,
            r[u].y = Math.random() * d) : (r[u].x = t + 5,
            r[u].y = Math.random() * d))
          }
          c.fill(),
          i(n)
      }
      var e = document.createElement("canvas")
        , i = requestAnimationFrame || msRequestAnimationFrame || function(t) {
          setTimeout(t, 16)
        }
      , a = 0
      , o = 0
      , r = [];
      t(),
      e.className = "snow",
      document.body.appendChild(e);
      for (var d = 0; o > d; d++)
        r.push({
            x: Math.random() * window.innerWidth,
            y: Math.random() * window.innerHeight,
            radius: 4 * Math.random() + 1,
            direction: 2 * Math.random() - .5
        });
      addEventListener("resize", t),
      i(n)
    }();
  </script>


  <script type="text/javascript">
    /* 评论自动跳转 */
    var jumpComments = function(){
      if(window.location.hash){
        var hash_decode = decodeURI(window.location.hash);
        if(!$(hash_decode).length){
          var checkExist = setInterval(function() {
            if ($(hash_decode).length) {
              clearInterval(checkExist);
              setTimeout(function(){
                $('html, body').animate({scrollTop: $(hash_decode).offset().top-90}, 1000);
              }, 1500);
            }
          }, 100);
        }
      }
    }
    $(document).ready(function(){
	    jumpComments();
    });
  </script>

 
 
 
 

<!-- cnzz -->
<style type="text/css">#cnzz_stat_icon_1258664352{display: none;}</style>
<script type="text/javascript">var cnzz_protocol = (("https:" == document.location.protocol) ? "https://" : "http://");document.write(unescape("%3Cspan id='cnzz_stat_icon_1258664352'%3E%3C/span%3E%3Cscript src='" + cnzz_protocol + "s4.cnzz.com/z_stat.php%3Fid%3D1258664352' type='text/javascript'%3E%3C/script%3E"));</script>
 

<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-150991779-1"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag("js", new Date());
  gtag("config", "UA-150991779-1");
</script>
 

  
</body>
</html>